<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>组件vModel</title>
  <script src="https://unpkg.com/vue@3"></script>
</head>
<body>
  <div id="app">
    <!-- custom-input组件使用vModel -->
    <div class="wrap">
      <h5 class="title">custom-input组件使用vModel</h5>
      <custom-input v-model="searchText"></custom-input>
      <p class="preview">绑定值为: {{ searchText }}</p>
    </div>
  </div>
</body>
<style>
  .wrap {
    background: #f3f3f3;
    padding: 10px;
    margin-bottom: 16px;
  }
  .wrap .title {
    margin: 0;
    margin-bottom: 20px;
    border-bottom: 1px solid #ddd;
    line-height: 2;
    font-size: 14px;
  }
  .wrap .preview {
    font-size: 13px;
  }
</style>
<script>
  const { createApp, defineProps, defineEmits, ref } = Vue

  const app = createApp({
    setup() {
      const searchText = ref('')
      return { searchText }
    }
  })
  // vue3.0+ v-model 等效于 modelValue 参数 + update:modelValue 事件
  app.component('custom-input', {
    props: {
      modelValue: { type: String, required: true }
    },
    emits: ['update:modelValue'],
    template: `
      <input type="text" 
        :value="modelValue" 
        @input="$emit('update:modelValue', $event.target.value)" 
      />
    `,
    // 注意这里没有写<script setup></script> 语法
    // 不能使用 defineProps 和 defineEmits 来定义 props 和 emits
    // 应该使用 props 和 emits 配置项
    

    // 错误示例1 (vue3.0+): 在setup钩子中直接写 defineProps 和 defineEmits
    // defineProps 和 defineEmits 和 <script setup> 绑定的, 在.vue组件文件中才可这样写
    /** 
     * setup() {
     *   const props = defineProps({ modelValue: {type: String, required: true} });
     *   const emits = defineEmits(['update:modelValue'])
     *   return { modelValue: props.modelValue, emits }
     * },
     * template: `
     *  <input type="text" 
     *   :value="modelValue" 
     *   @input="$emit('update:modelValue', $event.target.value)" 
     *  />
     * `,
     * 
    */


    // 错误示例2 (vue3.4+)：在setup钩子中直接写 defineModel
    // defineModel 和 <script setup> 绑定的, 在.vue组件文件中才可这样写
    /** 
     * setup() {
     *   const model = defineModel()
     *   return { model }
     * },
     * template: `
     *  <input type="text" 
     *   :value="model" 
     *   @input="model =  $event.target.value" 
     *  />
     * `,
     * 
    */
  })

  app.mount('#app')
</script>
</html>
